# -*- coding:utf-8 -*-
# 本文件负责将相对底层的功能实现，至于上面，借py2的国开装饰一下，，，
# func-->阿巴阿巴-->status: 404|505 :)
import os
import re
import json
import shutil
import random
import zipfile
import smtplib
import pandas as pd
import requests as rq
from .models import *
from datetime import timedelta
from email.header import Header
from string import ascii_letters
from chargpt_lfanke import Session
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication

dir_name = 'DaBai_v1'
default_info = json.load(open('.' + os.sep + dir_name + os.sep + 'baseinfo.json'))
rootdir = '.' + os.sep + dir_name
basedir = rootdir + os.sep + default_info['basedir']
tempdir = rootdir + os.sep + default_info['tempdir']
tipsdir = rootdir + os.sep + default_info['tipsdir']
storedir = rootdir + os.sep + default_info['storedir']
openai_api_keys = default_info['OpenAi API-Keys']
Session.API_KEYS = openai_api_keys

def chargpt(word: str) -> list[str]:
    return Session.get(word)

def log(*args, **kwargs):
    # 函数名字，信息，错误
    with open('log.txt', 'a') as fp:
        fp.write(f'{datetime.now()}--:{args}, {kwargs}\n')


def log_decorator(func, *args, **kwargs):  # 没有返回值的话自动状态码 ==》0
    def TODO(*args, **kwargs):
        try:
            return_item = func(*args, **kwargs)
            return {'status': 0} if not return_item else return_item
        except Exception as error:
            log(func.__name__, str((args, kwargs)), error)
        return {'status': 505}

    return TODO


@log_decorator
def registe(info, *args, **kwargs) -> dict:  # 绑定账号用，此前需要验证信息完整
    """_summary_

    Args:
        info (dict): key:班级(class_number),学号(id_number),姓名(name),QQ号(q_number)
    如果已经有绑定信息，返回绑定的信息，提示是否修改
    否则绑定先
    'status':绑定成功==》0；QQ与信息已绑定==》1；QQ与信息不符==》2（qq✔）;信息✔(3)，都不对(4)
    
    默认只能自己的QQ绑定自己QQ，所以QQ只有注册与未注册，学号到：已注册，未注册，注册信息不符
    """
    ser_q = user.objects.filter(q_number=info['q_number']).first()
    ser_id = user.objects.filter(id_number=info['id_number']).first()
    if not ser_id and not ser_q:
        user.objects.create(**info)
        return {'status': 0}
    elif ser_id == ser_q:  # 已经绑定正确
        return {'status': 1}
    elif not ser_id:  # qq已经绑定，学号未绑定对，返回之前绑定的学号
        return {'status': 2, 'error': ser_q.id_number}
    else:  # 学号绑定其他QQ，因为以QQ为主，所以必须其他退了才能梆
        return {'status': 3, 'error': ser_id.q_number}


@log_decorator
def upgrade_info(info, *args, **kwargs) -> dict:  # 修改绑定信息用
    """
    修改成功：0
    未注册：1
    """
    ser_q = user.objects.filter(q_number=info['q_number'])
    if ser_q.first():
        ser_q.update(**info)
        return {'status': 0}
    return {'status': 1}


@log_decorator
def drop_info(info, *args, **kwargs) -> dict:  # 注销用
    ser_q = user.objects.filter(q_number=info['q_number']).first()
    if ser_q:
        ser_q.delete()
    return {'status': 0}


@log_decorator
def view_info(info, *args, **kwargs) -> dict:  # 查看已经绑定的信息
    temp = user.objects.filter(q_number=info['q_number']).first()
    if not temp:
        return {'status': 1}
    return {'status': 0, 'id_number': temp.id_number, 'name': temp.name, 'class_number': temp.class_number}


@log_decorator
def recive_img(rec_info, file_address=False, *args, **kwargs) -> dict:  # 接受信息，查看是否已经提交，如果是则1，否则保存(0)
    """
    info : dict : q_number, task, urls[], option
    """
    temp = collecte.objects.filter(task=rec_info['task'], q_number=rec_info['q_number']).first()
    if temp:
        if not rec_info.get('option'):
            return {'status': 1}
        drop_img(pure(rec_info))
        # TODO 目前只支持一个图片或文件，日后支持多图片
    user_info = q_number_to_info(rec_info['q_number'])
    tail_address = '.jpg' if not file_address else file_address
    for i in rec_info['urls']:
        file_name = f"{re_name_pattern(task.objects.filter(name=rec_info['task']).first().pattern, user_info['name'], user_info['id_number'], user_info['class_number'])}" + f"{tail_address}"
        with open(basedir + os.sep + rec_info['task'] + os.sep + \
                  file_name, 'wb') as img:
            img.write(rq.get(i).content)
    collecte.objects.create(q_number_id=rec_info['q_number'], task_id=rec_info['task'],
                            img_path=file_name,
                            id_number=user_info['id_number'])
    return {'status': 0}


@log_decorator
def upgrade_img(rec_info, *args, **kwargs):
    if not collecte.objects.filter(task=rec_info['task'], q_number=rec_info['q_number']).first():
        if not rec_info.get('option'):
            return {'status': 1}
        else:
            return recive_img(pure(rec_info))
    else:  # 现在完全是覆盖
        drop_img(rec_info)
        return recive_img(pure(rec_info))


@log_decorator
def drop_img(rec_info, *args, **kwargs):
    try:
        for i in ','.join([j for i in
                           collecte.objects.filter(task_id=rec_info['task'], q_number=rec_info['q_number']).values(
                               'img_path') for j in i.values()]).split(','):
            os.remove(basedir + os.sep + rec_info['task'] + os.sep + i)
    except Exception as error:
        log("drop_img", str(rec_info), error)
    collecte.objects.filter(task_id=rec_info['task'], q_number=rec_info['q_number']).delete()
    return {'status': 0}


@log_decorator
def view_img(rec_info, *args, **kwargs):  # TODO 可能得按需更改
    temp = collecte.objects.filter(task=rec_info['task'], q_number=rec_info['q_number']).first()
    if not temp:
        return {'status': 1}
    return {'status': 0, 'path': [(basedir + os.sep + rec_info['task'] + os.sep + i) for i in temp.img_path.split(',')]}


@log_decorator
def create_task(task_info, *args, **kwargs):
    """
    创建任务，如果同名任务存在，返回任务信息
    否则创建任务。检查时间合理性；；
    信息包括：时间(begin,end,name,option[,sendto,re_name])
    此后：(未来)任务类型(文字、文件等等)
    
    成功：0，时间无效：1，名称无效：2
    """
    if task_info['begin'] >= task_info['end'] or \
            task_info['end'] < datetime.now():
        return {'status': 1}
    elif task.objects.filter(name=task_info['name']).first():
        if not task_info.get('option', '') == 'set':
            return {'status': 2}
        return upgrade_task(pure(task_info))
    else:
        try:
            os.mkdir(basedir + os.sep + task_info['name'])
            task.objects.create(**pure(task_info))
        except Exception as error:
            log('create_task', str(task_info), error)
            return {'status': 505}
        else:
            return {'status': 0}


@log_decorator
def upgrade_task(task_info, *args, **kwargs):  # 没有该任务则根据参数创建，没有参数返回报错
    temp = task.objects.filter(name=task_info['name'])
    if not temp.first():
        if not task_info.get('option', '') == 'create':
            return {'status': 1}
        return create_task(pure(task_info))
    # if temp.first().name != task_info['name']:     #  todo 因为暂时任务不改变名字，所以先注掉
    #     try:
    #         new = basedir+os.sep+task_info['name']
    #         src = basedir+os.sep+temp.first().name
    #         shutil.copytree(src, new)
    #         shutil.rmtree(src)
    #     except Exception as error:
    #         log('upgrade_task', str(task_info), error)
    #         return {'status': 505}
    temp.update(**pure(task_info))
    return {'status': 0}


@log_decorator
def drop_task(task_info, *args, **kwargs):
    temp = task.objects.filter(name=task_info['name'])
    try:
        for _ in task.objects.filter(name=task_info['name']):
            shutil.rmtree(basedir + os.sep + task_info['name'])
    except Exception as error:
        log("drop_img", str(task_info), error)
    temp.delete()
    return {'status': 0}


@log_decorator
def dump_to_store(task_name, file_path):  # TODO 未实现将表保存的功能，预计以后会放提交方法的压缩包
    temp = task.objects_all.filter(name=task_name).first()
    temp_store_dir = f"{storedir}{os.sep}{temp.begin.year}{temp.begin.month}{temp.begin.day}{temp.name}.zip"
    shutil.copy(file_path, temp_store_dir)
    os.remove(file_path)
    store.objects.create(task=task_name, table_path=temp_store_dir)
    shutil.rmtree(basedir + os.sep + task_name)
    task.objects_all.filter(name=task_name).delete()


@log_decorator
def remind_task(task_name, *args, **kwargs):  # 获取手动提醒名单，存在res['info']里面，是qq号列表
    temp = task.objects.filter(name=task_name).first()
    if not temp:
        return {'status': 1}
    res = []
    for i in user.objects.exclude(q_number__in=collecte.objects.filter(task_id=task_name).values('q_number_id')):
        res.append(
            i.q_number
        )
    return {'status': 0, 'info': res}


@log_decorator
def complete_task(task_name, *args, **kwargs):  # 将任务设置为完成且手动提交任务  📪
    temp = task.objects_all.filter(name=task_name)
    if not temp.first():
        return {'status': 1}
    temp.update(is_complete=True)
    temp = temp.first()
    try:
        file_path = tempdir + os.sep + (task_name if not temp.re_name else temp.re_name) + '.zip'
        zip_file = zipfile.ZipFile(file_path, 'w')
        for i in os.listdir(basedir + os.sep + task_name):
            zip_file.write(basedir + os.sep + task_name + os.sep + i, i)
        zip_file.close()
        default_send([file_path], temp.send_to)
    except Exception as error:
        log('complete_task', str(task_name), error)
        return {'status': 505}
    else:
        return dump_to_store(task_name, file_path)


@log_decorator
def view_task(task_info, *args, **kwargs):
    if 'option' in task_info:
        tob = task.objects_all
    else:
        tob = task.objects
    temp = tob.filter(name=task_info['name']).first()
    if not temp:
        return {'status': 1}
    else:
        return {
            'status': 0,
            'name': temp.name,
            'send_to': temp.send_to,
            'begin': temp.begin,
            'end': temp.end,
            're_name': temp.re_name,
            'is_complete': temp.is_complete,
            'process_bar': collecte.objects.filter(task_id=temp.name).count() / (
                31 if not user.objects.all().count() else user.objects.all().count()),
            'not_hand_in': [i.name for i in user.objects.exclude(
                q_number__in=collecte.objects.filter(task_id=temp.name).values('q_number'))],
            'describe': temp.describe,
            'pattern': temp.pattern,
        }


@log_decorator
def view_all_tasks(option=None, *args, **kwargs):  # 如果有参数则看全部，否则看最近
    tob = task.objects_all if option else task.objects
    temp = tob.all()
    res = []
    for i in temp:
        res.append(
            {
                'name': i.name,
                'send_to': i.send_to,
                'begin': i.begin,
                'end': i.end,
                're_name': i.re_name,
                'is_complete': i.is_complete,
                'process_bar': collecte.objects.filter(task_id=i.name).count() / (
                    31 if not user.objects.all().count() else user.objects.all().count()),
                'not_hand_in': [j.name for j in user.objects.exclude(
                    q_number__in=collecte.objects.filter(task_id=i.name).values('q_number'))],
                'describe': i.describe,
                'pattern': i.pattern,
            }
        )
    return {'status': 0, 'info': res}


@log_decorator
def view_sim_tasks(option=None, *args, **kwargs):
    res = []
    tob = task.objects_all if option else task.objects
    for i in tob.all():
        res.append(
            (

                i.name,
                (collecte.objects.filter(task_id=i.name).count() / (
                    31 if not user.objects.all().count() else user.objects.all().count()))

            )
        )
    return {'status': 0, 'info': res}


@log_decorator
def view_my_tasks(q_number, *args, **kwargs):
    temp = task.objects.exclude(name__in=collecte.objects.filter(q_number_id=q_number).values('task_id'))
    res = []
    for i in temp:
        res.append(
            {
                'name': i.name,
                'begin': i.begin,
                'end': i.end,
                'describe': i.describe,
            }
        )
    return {'status': 0, 'info': res}


@log_decorator
def pure(dict_obj, *args, **kwargs):
    if 'option' in dict_obj:
        dict_obj.pop('option')
    return dict_obj


@log_decorator
def get_orders(option=None, *args, **kwargs):  # 获取命令集
    now = datetime.now()
    match option:
        case '任务':
            return [f'''创建任务：任务名字
结束时间：{now.year}年{now.month}月{now.day}日xx点xx分
提交至：邮箱，在任务完成后会自动打包发送
压缩包命名：打包后压缩包的名字
命名模板：有班级(软件2132)、班号(2132)、姓名、学号
文件类型：file或image
任务描述：阿巴巴巴
''', f'''修改任务：任务名字
结束时间：{now.year}年{now.month}月{now.day}日xx点xx分
提交至：邮箱，在任务完成后会自动打包发送
压缩包命名：打包后压缩包的名字
命名模板：有班级(软件2132)、班号(2132)、姓名、学号
文件类型：file或image
任务描述：阿巴巴巴''', '''删除任务：任务名字''',
                    '''完成任务：任务名字     不管交了多少，直接打包发送''',
                    '''任务提醒：任务名字     私聊提醒没交作业的人''', '''查看任务：任务名字   查看任务详情

查看所有任务：     查看所有任务详情

查看所有任务完成情况：       查看所有任务完成百分比''']
        case '提醒':
            return [rf'''创建提醒：提醒名字
提醒时间：{now.year}年{now.month}月{now.day}日xx点xx分
提醒方式：0|1|2           0：群+私发，1：群提醒，2：私发提醒
提醒内容：阿巴巴''', '''查看提醒：提醒名字

删除提醒：提醒名字''']
        case '报数':
            return ['''开始报数：阿巴阿巴     创建报数任务，此期间机器人会收集群员[：]后面的内容

提醒报数：群聊/私发提醒报数(选择暂时未上线)

查看报数：

停止报数：            停止并发送报数结果至发起人邮箱

删除报数：删除报数任务，由于某些原因，一时间只允许一个报数任务
：阿巴阿巴''', '''一般情况同一时间只允许一个报数任务存在''']
        case '绑定':
            return ['''注册：        将信息与QQ号绑定
姓名：
班级：
学号：''', '''修改信息：  修改与QQ号绑定的信息
姓名：
班级：
学号：''', '''解绑：         将绑定信息删除''']
        case '全部':
            return [r'''https://gitee.com/i_am_lfanke/da-bai_v1/blob/master/README.md，目前支持：任务、提醒、注册、请假、热点、全部、报数''']
        case '热点':
            return [r'''get热点：关键字''']
        case 'key':
            return ['key：待记录的关键字\n信息msg', 'get keys：', 'get key：key名字', '完成key：key名字\nevaluate...', '移除key：key']
        case '资金':
            return [
                '创建源资金：银行/来源名字',
                '查看资金：名字',
                '所有源资金：',
                '查看所有资金：',
                '记录资金：名字\n银行/来源名字：-0.95',
                '一些可以加上”细节“这个可选项！'
            ]
        case '暂存':
            return [
                '文件暂存：文件名\n评论', '获取文件暂存：文件名(未开放)', '只能先发文件！获取看邮箱，不支持大文件...',
                '而且，，，记得名字是文件名，还带后缀，目前大白存文件没有后缀！'
            ]
        case _:
            return ['''我的任务：     查看最近在机器人上布置的、我未提交的作业''',
                    '''提交任务：任务名字       如果有图片后缀，那么将提交图片至任务，如果是文件则等待文件上传
如： 提交任务：第四季第八期青年大学习   (手机QQ点+选择图片一起发)''',
                    '''清空缓存任务：         上传文件的任务在先发文件或先发任务时创建缓存，每次只能有一个缓存(以后改)''',
                    '''key、资金、热点、暂存...''', '''q：话，和chargpt对话...''']


@log_decorator
def q_number_to_info(q_number, *args, **kwargs):
    who = user.objects.filter(q_number=q_number).first()
    if not who:
        return who
    return {
        'name': who.name,
        'q_number': who.q_number,
        'id_number': who.id_number,
        'class_number': who.class_number,
        'is_root': who.is_root,
    }


@log_decorator
def id_number_to_info(id_number, *args, **kwargs):
    who = user.objects.filter(id_number=id_number).first()
    if not who:
        return who
    return {
        'name': who.name,
        'q_number': who.q_number,
        'id_number': who.id_number,
        'class_number': who.class_number,
        'is_root': who.is_root,
    }


@log_decorator
def is_root(number, *args, **kwargs):
    return q_number_to_info(number) or id_number_to_info(number)


@log_decorator
def create_statistic(event, q_number):  # 群内报数任务创建，目前支持没有关键字转化的报数(关键字转化：(1：是，2：否)转化记录于导出的地方)
    temp_event = statistic_event.objects.filter(name=event)
    if temp_event.first():  # 此时已存在报数任务，报数完成自动停止
        return {'status': 1, 'error': '报数任务已存在！要创建请删除/停止前一个任务！\n[删除报数：]或[停止报数：]'}
    temp_event.create(name=event, q_number_id=q_number)
    return {'status': 0}


# 由于多报数任务未那啥，所以直接看所有===看一个，，，
@log_decorator
def view_statistic(event=None):  # 直接看所有的报数任务情况
    if not event:
        event = get_curr_statistic_event()
        if event['status'] == 1:
            return event
        else:
            temp_event = event['info']
    else:
        temp_event = statistic_event.objects.filter(name=event)
    if not temp_event:
        return {'status': 1, 'error': '没有查询到相关报数任务，可能是任务已完成或被删除'}
    else:
        new_temp_event = statistics_event_collecte.objects.filter(event_id=event['info'])
        res = dict()
        ex_res = [j for i in user.objects.exclude(q_number__in=new_temp_event.values('q_number_id')).values('name') for
                  j in i.values()]
        # 将数据组织一下吧，，，
        for i in new_temp_event:
            if i.info in res:
                res[i.info].append(q_number_to_info(i.q_number_id)["name"])
            else:
                res[i.info] = [q_number_to_info(i.q_number_id)["name"]]
    return {'status': 0, 'info': res, 'not': ex_res}


@log_decorator
def get_not_statistic(event=None):  # 获取没有报数人的QQ
    if not event:
        event = get_curr_statistic_event()
    if event['status'] == 1:
        return event
    else:
        event = event['info']
    if statistic_event.objects.filter(name=event):
        new_temp_event = statistics_event_collecte.objects.filter(event=event)
        res = user.objects.exclude(q_number__in=new_temp_event.values('q_number_id')).values('q_number')
        return {'status': 0, 'info': [j for i in res for j in i.values()]}
    else:
        return {'status': 1, 'error': '任务不存在或已删除'}


@log_decorator
def get_curr_statistic_event():
    event = statistic_event.objects.all().order_by('-time').first()
    if event:
        return {'status': 0, 'info': event.name}
    else:
        return {'status': 1, 'error': '没有报数任务！！！'}


@log_decorator
def drop_statistic(event=None):  # 直接删除报数任务
    if not event:
        event = get_curr_statistic_event()
    if event['status'] == 1:
        return event
    else:
        event = event['info']
    temp_event = statistic_event.objects.filter(name=event)
    temp_event.delete()
    return {'status': 0}


@log_decorator
def statisticing(q_number, info, event=None):  # 将群员的报数信息储存或更新
    if not event:
        event = get_curr_statistic_event()
        if event['status'] == 1:
            return event
        else:
            event = event['info']
    temp = statistics_event_collecte.objects.filter(q_number_id=q_number)
    if temp.first():
        temp.update(info=info)
    else:
        temp.create(info=info, q_number_id=q_number, event_id=event)
    return {'status': 0}


@log_decorator
def build_and_send_result(event=None, q_number=None):  # 将结果打包发送至发起人QQ邮箱（如果QQ号为空）
    if not event:
        event = get_curr_statistic_event()
    if event['status'] == 1:
        return event
    else:
        event = event['info']
    temp_event = statistic_event.objects.filter(name=event)
    temp_collect = statistics_event_collecte.objects.filter(event_id=event)
    if not temp_event.first():
        return {'status': 1, 'error': '没有该任务的信息！'}
    else:
        df = pd.DataFrame({'班级': [], '姓名': [], '学号': [], '填写内容': []})
        df.set_index('学号', inplace=True)
        for i in temp_collect:
            ttp = q_number_to_info(i.q_number_id)
            df.loc[ttp['id_number']] = [ttp['class_number'], ttp['name'], i.info]
        dfc = df.loc[:, ['班级', '填写内容', '姓名']].groupby(['班级', '填写内容']).count()
        file_temp_name = ''.join(random.choices(ascii_letters, k=8)) + '.xlsx'
        xlp = pd.ExcelWriter(f'{tempdir + os.sep + file_temp_name}')
        df.to_excel(xlp, sheet_name='数据总览')
        dfc.to_excel(xlp, sheet_name='数据统计')
        xlp.save()
        xlp.close()
        default_send([f'{tempdir + os.sep + file_temp_name}'], To=f'{temp_event.first().q_number_id}@qq.com'
        if not q_number else f'{q_number}@qq.com', text=event,
                     header=f'你{temp_event.first().time}在群里发起的群投票结果')
        os.remove(f'{tempdir + os.sep + file_temp_name}')
        return {'status': 0}


@log_decorator
def build_email(text: str = None, mode="plain", encoding="utf-8", header=None, From=None, To=None, files: list = None,
                images: list = None, *args, **kwargs):
    widgets = []
    widgets.append(MIMEText(text, mode, encoding))  # 邮件正文
    if files:
        if not header:
            header = os.path.splitext(os.path.basename(files[0]))[0]
        for i in files:
            temp = MIMEApplication(open(i, 'rb').read())
            temp.add_header('Content-Disposition', 'attachment', filename=i.split(os.sep)[-1])  # 附件信息
            widgets.append(temp)
    if images:
        for i in files:
            temp = MIMEImage(open(i, 'rb').read(), _subtype='octet-stream')
            temp.add_header('Content-Disposition', 'attachment', filename=i.split(os.sep)[-1])  # 附件信息
            widgets.append(temp)
    mail = MIMEMultipart()
    for i in widgets:
        mail.attach(i)
    mail['Subject'] = Header(header, encoding)  # 邮件主题
    mail['From'] = Header(From, encoding)  # 发件人
    mail['To'] = Header(To, encoding)  # 收件人
    return {'status': 0, 'mail': mail}


@log_decorator
def send_email(user, password, server, port: int, To: list, mail, From=None, *args, **kwargs):
    server = smtplib.SMTP_SSL(server, port)
    server.login(user, password)
    if not From:
        From = user
    server.sendmail(From, To, mail.as_string())
    server.quit()


@log_decorator
def default_send(files: list, To, *args, **kwargs):
    mail = build_email(files=files, *args, **kwargs)['mail']
    mail['From'] = Header(default_info['email']['user'], 'utf-8')
    mail['To'] = Header(To, 'utf-8')
    send_email(
        user=default_info['email']['user'],
        password=default_info['email']['passcode'],
        server=default_info['email']['smtp']['server'],
        port=default_info['email']['smtp']['port'],
        To=To,
        mail=mail, )


@log_decorator
def str_to_datatime(s, *args, **kwargs):
    # if s in ['今天', '现在']:
    # s = datetime.now().strftime(r"%Y-%m-%d %H:%M:%S")
    s = s.strip()
    res_time = None
    try:
        res_time = pd.to_datetime(s)
    except:
        res_time = datetime.strptime(s, r'%Y年%m月%d日%H点%M分')
    return res_time


@log_decorator
def create_tip(name, text, images: list = list(), begin=datetime.now(), method=0):
    temp_qr = tip.objects.filter(name=name)
    if temp_qr.first():
        return {'status': 1, 'error': '名称重复'}
    local_images = list()
    os.mkdir(tipsdir + os.sep + name)
    for i in enumerate(images):
        with open(tipsdir + os.sep + name + os.sep + f'{i[0]}.jpg', 'wb') as fp:
            fp.write(rq.get(i[1]).content)
        local_images.append(tipsdir + os.sep + name + os.sep + f'{i[0]}.jpg')
    temp_qr.create(name=name, begin=begin, method=method,
                   tips=text, images=','.join(local_images))
    return {'status': 0}


@log_decorator
def get_tips():
    return {
        'status': 0,
        'info': [
            i for i in tip.objects.all()
        ]
    }


@log_decorator
def drop_tip(name):
    temp_tip = tip.objects.filter(name=name)
    for _ in temp_tip:
        shutil.rmtree(tipsdir + os.sep + name)
    temp_tip.delete()
    return {'status': 0}


# 这里的方法全部是生成对应CQcode，最后组合起来以text形式talk或者talks即可
@log_decorator
def ats(q_numbers: list = None, all=None) -> str:
    # 优先判断all
    if all:
        return '[CQ:at,qq=all,name=全体成员]'
    return ' '.join([f'[CQ:at,qq={i},name={i}]' for i in q_numbers])


@log_decorator
def images(urls: list, type='show', magic=40000, value=0) -> str:
    return ''.join(
        [
            f'[CQ:image,file={path},type={type},id={magic},value={value}]'
            if path.startswith('http') else
            f'[CQ:image,file=file:///{os.path.abspath(path)},type={type},id={magic},value={value}]'
            for path in urls
        ]
    )


@log_decorator
def totext(text) -> str:
    return f'{text}'


@log_decorator
def title(text, qq: int = default_info['self_q_number'], time=None) -> str:
    # if not time:
    # time = int(datetime.timestamp(datetime.now()))
    # 将回复模拟美化为标题（伪）
    # return f'[CQ:reply,text={text},qq={qq},time={time}]'
    return f'{text}\n'


@log_decorator
def re_name_pattern(pattern, name, id_number, class_number, *args, **kwargs):
    """
    暂时只匹配替换名字、学号、班级，格式：姓名、班号(2132)、班级(软件2132)、学号
    非关键字得有\表示反转义
    """
    pattern = re.sub(r'(?<!\\)姓名', f'{name}', pattern)
    pattern = re.sub(r'(?<!\\)班号', f'{class_number}', pattern)
    pattern = re.sub(r'(?<!\\)班级', f'软件{class_number}', pattern)
    pattern = re.sub(r'(?<!\\)学号', f'{id_number}', pattern)
    pattern = re.sub(r'(?<=\\)姓名', f'姓名', pattern)
    pattern = re.sub(r'(?<=\\)班号', f'班号', pattern)
    pattern = re.sub(r'(?<=\\)班级', f'班级', pattern)
    pattern = re.sub(r'(?<=\\)学号', f'学号', pattern)
    return pattern
